package ai4games_tests.guides;

import game2dai.World;
import game2dai.entities.Building;
import game2dai.entityshapes.ps.BuildingPic;
import game2dai.graph.Graph;
import game2dai.graph.GraphEdge;
import game2dai.graph.GraphNode;
import game2dai.maths.FastMath;
import game2dai.maths.Geometry2D;
import game2dai.maths.Vector2D;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;

import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PGraphicsJava2D;
import processing.core.PImage;
import processing.core.PVector;

public class GuidePics extends PApplet {

	int pic = 16;
	PFont font14, font12, font11, font10, font8;

	public void setup(){
		switch(pic){
		case 1:
		case 3:
		case 4:
			w = h = 300;
			break;
		case 2:
		case 5:
		case 10:
		case 16:
			w = 300;
			h = 200;
			break;
		case 6:
			w = 300;
			h = 150;
			break;
		case 7:
			w = 260;
			h = 80;
			break;
		case 8:
			w = 260;
			h = 150;
			break;
		case 9:
			w = 270;
			h = 200;
			break;
		case 11:
		case 15:
			w = 200;
			h = 200;
			break;
		case 12:
			w = 600;
			h = 300;
			break;
		case 13:
			w = 300;
			h = 480;
			break;
		case 14:
			w = 230;
			h = 150;
			break;
		}
		size(w,h);
		background(250);
		YELLOW = color(255,255,0);
		YELLOW0 = color(255,255,200);
		RED = color(200,0,0);
		PINK = color(255,200,200);
		PINK0 = color(255,100,100);
		BLACK = color(0);
		WHITE = color(255);
		GREY0 = color(160);
		GREY1 = color(128);
		GREY2 = color(220);
		BLUE = color(0,0,200);
		BLUE0 = color(200,200,255);
		CYAN = color(0,200,200);
		CYAN0 = color(0,255,255);
		GREEN0 = color(0,128,0);
		GREEN1 = color(200,255,200);
		GREEN2 = color(100,200,100);
		GREEN_1 = color(100,255,100,160);
		PURPLE = color(255,64,255);
		YELLOW_0 = color(255,255,0,128);

		font8 = createFont("Sans serif", 8);
		font10 = createFont("Sans serif", 10);
		font11 = createFont("Sans serif", 11);
		font12 = createFont("Sans serif", 12);
		font14 = createFont("Sans serif", 14);

		pg = (PGraphicsJava2D) g;
		g2 = pg.g2;

		switch(pic){
		case 1:
			seekPic();
			break;
		case 2:
			wanderPic();
			break;
		case 3:
			pursuePic();
			break;
		case 4:
			evadePic();
			break;
		case 5:
			ostacleAvoidPic_1();
			break;
		case 6:
			ostacleAvoidPic_2();
			break;
		case 7:
			wallAvoidPic_1();
			break;
		case 8:
			wallAvoidPic_2();
			break;
		case 9:
			interposePic();
			break;
		case 10:
			hidePic();
			break;
		case 11:
			pathPic();
			break;
		case 12:
			offsetPic();
			break;
		case 13:
			groupPic1();
			break;
		case 14:
			nonpenPic();
			break;
		case 15:
			buildPic_1();
			break;
		case 16:
			pathPic_1();
			break;
		}
		saveFrame(fname);
	}


	public void pathPic_1(){
		int bg = color(40,128,40);
		int nodeCol = color(255);
		int[] edgeCol = { color(200), color(0, 255, 0), color(0, 255, 0) };
		background(bg);
		
		int mode = 1;
		fname = "path0"+ (mode + 1) + ".jpg";
		Graph g = getGraph_A();
		drawNodes(g.getNodeArray(),new double[] { 130, 260, 70, 225, 340, 45}, nodeCol);
		drawEdges(g, edgeCol, mode);
		println(g.getNbrEdges());
	}

	private void drawNodes(GraphNode[] g, double[] offAng, int col){
		textFont(font14);
		float x,y, dx, dy;
		double a;
		String id;
		pushStyle();
		ellipseMode(CENTER);
		fill(col);
		noStroke();
		for(int i = 0; i < g.length; i++){
			x = g[i].xf();
			y = g[i].yf();
			a = FastMath.toRadians(offAng[i]);
			dx = (float) (12 * FastMath.cos(a));
			dy = (float) (14 * FastMath.sin(a) + 4);

			ellipse(x, y, 6, 6);
			id = "" + g[i].id();
			fill(col);
			text(id, x + dx - textWidth(id)/2, y + dy );
		}
		popStyle();
	}

	private void drawEdges(Graph g, int[] col, int mode){
		textFont(font11);
		int n = g.getNbrNodes();
		for(int id0 = 1; id0 < n; id0++)
			for(int id1 = id0+1; id1 <= n; id1++){
				if(mode == 0)
					drawEdgeC(g, id0, id1, col[mode]);
				else
					drawEdge(g, id0, id1, col[mode], mode);

			}

	}

	private void drawEdgeC(Graph g, int id0, int id1, int col){
		GraphEdge[] e = new GraphEdge[2];
		e[0] = g.getEdge(id0, id1);
		e[1] = g.getEdge(id1, id0);
		if(e[0] == null && e[1] == null)
			return;

		GraphNode n0 = g.getNode(id0);
		GraphNode n1 = g.getNode(id1);

		float dir = (float) FastMath.atan2(n1.y() - n0.y(), n1.x() - n0.x());
		float mag = round((float) Geometry2D.distance(n0.x(), n0.y(), n1.x(), n1.y()));

		float thickness = 2.5f;

		// Prepare to draw the edge
		pushStyle();
		ellipseMode(CENTER);
		strokeWeight(thickness);
		stroke(col);
		fill(col);

		pushMatrix();
		translate(n0.xf(), n0.yf());
		rotate(dir);

		stroke(col);
		// Draw the line between ends
		line(4, 0, mag-4,0);
		popMatrix();
		popStyle();

	}

	private void drawEdge(Graph g, int id0, int id1, int col, int mode){
		GraphEdge[] e = new GraphEdge[2];
		e[0] = g.getEdge(id0, id1);
		e[1] = g.getEdge(id1, id0);
		if(e[0] == null && e[1] == null)
			return;

		float[] offsetY = {0, 0};
		if(e[0] != null && e[1] != null){
			offsetY[0] = 2; offsetY[1] = -2;
		}

		String label[] = { "", "" };
		label[0] = (e[0] != null) ? "" + (int) FastMath.round(e[0].getCost()) : "";
		label[1] = (e[1] != null) ? "" + (int) FastMath.round(e[1].getCost()) : "";

		GraphNode n0 = g.getNode(id0);
		GraphNode n1 = g.getNode(id1);

		float dir = (float) FastMath.atan2(n1.y() - n0.y(), n1.x() - n0.x());
		float mag = round((float) Geometry2D.distance(n0.x(), n0.y(), n1.x(), n1.y()));

		float thickness = 1.1f;

		// Prepare to draw the edge
		pushStyle();
		ellipseMode(CENTER);
		strokeWeight(thickness);
		stroke(col);
		fill(col);

		pushMatrix();
		translate(n0.xf(), n0.yf());
		rotate(dir);

		for(int i = 0; i < e.length; i++){
			if(e[i] != null){
				println(e[i]);
				pushMatrix();
				translate(0, offsetY[i]);
				float x0 = 6;
				float x1 = mag - 6;
				stroke(col);
				// Draw the line between ends
				line(x0, 0, x1, 0);

				// Draw the end
				switch(i){
				case 1:
					beginShape(PApplet.TRIANGLES);
					vertex(x0,0);
					vertex(x0 + 4 * thickness,- 2* thickness);
					vertex(x0 + 4 * thickness,  2* thickness);
					endShape(PApplet.CLOSE);
					break;
				case 0:
					beginShape(PApplet.TRIANGLES);
					vertex(x1, 0);
					vertex(x1 - 4 * thickness, -2* thickness);
					vertex(x1 - 4 * thickness,  2* thickness);
					endShape(PApplet.CLOSE);
					break;
				}
				if(mode == 2){
					if(label[i].length() > 0){
						noStroke();
						float px = (mag - textWidth(label[i]))/2;		
						float py = (i == 1) ? -2 - 2 * thickness : 10 +  2 * thickness ;
						text(label[i], px, py);
					}
				}
				popMatrix();
			}
		}
		popMatrix();
		popStyle();

		println();

	}

	private Graph getGraph_A(){
		Graph graph = new Graph();
		GraphNode node;
		//                  ID   X    Y
		node = new GraphNode(1, 30, 180);
		graph.addNode(node);
		node = new GraphNode(2, 40, 40);
		graph.addNode(node);
		node = new GraphNode(3, 110, 90);
		graph.addNode(node);
		node = new GraphNode(4, 215, 135);
		graph.addNode(node);
		node = new GraphNode(5, 255, 50);
		graph.addNode(node);
		node = new GraphNode(6, 260, 155);
		graph.addNode(node);

		double cost;

		cost = graph.distance(1, 2);
		graph.addEdge(1, 2, cost);

		cost = graph.distance(1, 3);
		graph.addEdge(1, 3, cost, cost);

		cost = graph.distance(1, 4);
		graph.addEdge(1, 4, cost, cost);

		cost = graph.distance(2, 5);
		graph.addEdge(2, 5, cost, cost);

		cost = graph.distance(3, 2);
		graph.addEdge(3, 2, cost);

		cost = graph.distance(3, 5);
		graph.addEdge(3, 5, cost, cost);

		cost = graph.distance(4, 5);
		graph.addEdge(4, 5, cost, cost);

		cost = graph.distance(4, 6);
		graph.addEdge(4, 6, cost, cost);

		return graph;
	}

	public class Line {

		public Line(int mode, float x, float y, float v0, float v1, int lineCol, float lineWeight, int lineStyle, int startEndStyle, int endLineStyle){
			this.col = lineCol;
			thickness = lineWeight;
			this.lineStyle = lineStyle;
			e0Style = startEndStyle;
			e1Style = endLineStyle;

			sx = x;
			sy = y;
			if(mode == DIR){
				mag = v0;
				dir = v1;
				ex = sx + mag * cos(dir);
				ey = sy + mag * sin(dir);				
			}
			else {
				ex = v0;
				ey = v1;
				mag = sqrt((ex-sx)*(ex-sx) + (ey-sy)*(ey-sy));
				dir = atan2(ey-sy, ex-sx);
			}
			dashed =  new BasicStroke(thickness,
					BasicStroke.CAP_BUTT,
					BasicStroke.JOIN_ROUND,
					0, dash1, 0);
			solid =  new BasicStroke(thickness,
					BasicStroke.CAP_BUTT,
					BasicStroke.JOIN_ROUND,
					0, null, 0);
			tcol = color(0);

		}

		public void setText(String text, int hpos, int vpos, int pad){
			label = text;
			this.hpos = hpos;
			this.vpos = vpos;
			this.pad = pad;
		}

		public void setDash(float[] dash){
			dash1 = dash;
			dashed =  new BasicStroke(thickness,
					BasicStroke.CAP_BUTT,
					BasicStroke.JOIN_ROUND,
					0, dash1, 0);
		}

		public void setTextCol(int col){
			tcol = col;
		}

		public void draw() {
			// Prepare to draw the entity
			pushStyle();
			ellipseMode(CENTER);
			pushMatrix();
			translate(sx, sy);
			rotate(dir);

			Color jcol = new Color(col);

			// Draw the line between ends
			g2.setColor(jcol);
			if(lineStyle == DASHED)
				g2.setStroke(dashed);
			else
				g2.setStroke(solid);			
			g2.drawLine(0, 0,round(mag),0);

			// Draw the ends
			g2.setStroke(solid);
			stroke(col);
			strokeWeight(thickness);
			fill(col);

			switch(e0Style){
			case ARROW:
				beginShape(PApplet.TRIANGLES);
				vertex(0,0);
				vertex(4 * thickness,- 2* thickness);
				vertex(4 * thickness,  2* thickness);
				endShape(PApplet.CLOSE);
				break;
			case LINE:
				line(0, 2* thickness, 0, -2* thickness);
				break;
			case BALL:
				ellipse(0,0, 4*thickness, 4*thickness);
				break;				
			}

			switch(e1Style){
			case ARROW:
				beginShape(PApplet.TRIANGLES);
				vertex(mag,0);
				vertex(mag - 4 * thickness,- 2* thickness);
				vertex(mag - 4 * thickness,  2* thickness);
				endShape(PApplet.CLOSE);
				break;
			case LINE:
				line(mag, 2* thickness, mag, -2* thickness);
				break;
			case BALL:
				ellipse(mag,0, 4*thickness, 4*thickness);
				break;				
			}
			if(label.length() > 0){
				noStroke();
				fill(tcol);
				float px;
				switch(hpos){
				case LEFT:
					px = pad;
					break;
				case RIGHT:
					px = mag - pad - textWidth(label);
					break;
				default:
					px = (mag - textWidth(label))/2;
				}
				float py;
				switch(vpos){
				case BELOW:
					py = 12 +  2 * thickness;
					break;
				default:
					py = -2 - 2 * thickness;
				}
				text(label, px, py);
			}

			// Finished drawing
			popMatrix();
			popStyle();
		}		


		public void moveStartTo(float nx, float ny){
			sx = nx;
			sy = ny;
			ex = sx + mag * cos(dir);
			ey = sy + mag * sin(dir);				
		}

		public PVector getTip(){
			return new PVector(ex,ey);
		}

		public PVector getMidPoint(){
			return new PVector((ex+sx)/2,(ey+sy)/2);
		}

		public BasicStroke solid;
		public BasicStroke dashed;
		public float dash1[] = { 6.0f };
		public int lineStyle = SOLID;

		private int e0Style = NONE;
		private int e1Style = NONE;

		private String label = "";
		private float pad = 0;
		private float tcol = 0;
		private int hpos = CENTER;
		private int vpos = ABOVE;


		private float sx, sy, ex, ey, mag, dir;
		private int col;
		private float thickness;
	}


	public class Dart{
		private float px, py;
		private float angle;
		private float dartLength = 20;
		private float[] x = new float[] {0.5f * dartLength, -0.4f * dartLength, -0.4f * dartLength};
		private float[] y = new float[] {0, 0.3f * dartLength, -0.3f * dartLength};

		private int fillCol;
		private int strokeCol;
		private float strokeWeight;

		private float detectBoxLength = 0;
		private float whiskerLength = 0;

		public Dart(){
			fillCol = color(255);
			strokeCol = color(0);
			strokeWeight = 1;
		}

		public Dart(float px, float py, float length, float ang, int fill, int stroke, float weight){
			this.px = px;
			this.py = py;
			angle = ang;
			fillCol = fill;
			strokeCol = stroke;
			strokeWeight = weight;
			dartLength = length;
			x = new float[] {0.5f * dartLength, -0.4f * dartLength, -0.4f * dartLength};
			y = new float[] {0, 0.3f * dartLength, -0.3f * dartLength};
		}


		/**
		 * @param detectBoxLength the detectBoxLength to set
		 */
		public void setDetectBoxLength(float detectBoxLength) {
			this.detectBoxLength = detectBoxLength;
		}

		/**
		 * @param whiskerLength the whiskerLength to set
		 */
		public void setWhiskerLength(float whiskerLength) {
			this.whiskerLength = whiskerLength;
		}

		public void draw() {
			// Prepare to draw the entity
			pushStyle();
			pushMatrix();
			translate(px, py);
			rotate(angle);

			// Draw the entity
			stroke(PURPLE);
			strokeWeight(1.2f);
			if(detectBoxLength > 0){
				noFill();
				rect(-0.4f*dartLength,-0.32f*dartLength, detectBoxLength, 0.64f*dartLength);
			}
			if(whiskerLength > 0){
				float fov = 0.7f * PI;
				int nbr = 3;
				float sa = -fov/2;
				float da = fov/(nbr-1);
				for(int i = 0; i < nbr; i++){
					float a = sa + i * da;
					float tipX = whiskerLength * cos(a) * (0.2f + 0.8f * abs(cos(a)));
					float tipY = whiskerLength * sin(a) * (0.2f + 0.8f * abs(cos(a)));
					line(0,0,tipX, tipY);
				}
			}
			stroke(strokeCol);
			if(strokeWeight > 0)
				strokeWeight(strokeWeight);
			else 
				noStroke();
			fill(fillCol);
			beginShape(PApplet.TRIANGLES);
			vertex(x[0],y[0]);
			vertex(x[1],y[1]);
			vertex(x[2],y[2]);
			endShape(PApplet.CLOSE);

			// Finished drawing
			popMatrix();
			popStyle();
		}

		public void setPos(float x, float y, float ang){
			px = x;
			py = y;
			angle =ang;			
		}

		public void setPos(float x, float y){
			px = x;
			py = y;
		}

		public void appearance(int fill, int stroke, float weight){
			fillCol = fill;
			strokeCol = stroke;
			strokeWeight = weight;
		}
	}

	public class Bitmap {
		PImage img;
		private float sx, sy, angle;

		public Bitmap(PImage img, float sx, float sy, float angle){
			this.img = img;
			this.sx = sx;
			this.sy = sy;
			this.angle = angle;
		}

		public void draw(){
			pushStyle();
			pushMatrix();
			translate(sx,sy);
			rotate(angle);
			imageMode(CENTER);
			image(img,0,0);
			popMatrix();
			popStyle();
		}
	}

	public class Target{
		private float sx, sy, size;
		private int col;
		private float thickness;

		/**
		 * Create an arrow 20 units long and 12 units at its thick end with a white body
		 * and thin black border.
		 * @param papp
		 */
		public Target(){
			col = color(255);
			thickness = 1;
		}

		public Target(float x, float y, float size, int col, float weight){			
			this.col = col;
			thickness = weight;
			sx = x;
			sy = y;
			this.size = size;
		}

		public void draw() {
			// Prepare to draw the entity
			pushStyle();
			pushMatrix();
			translate(sx, sy);

			// Draw the entity
			stroke(col);
			strokeWeight(thickness);
			noFill();
			line(-size/2,0,size/2,0);
			line(0,-size/2,0,size/2);
			ellipse(0,0,0.8f*size, 0.8f*size);

			// Finished drawing
			popMatrix();
			popStyle();
		}

		public void appearance(int fill, float weight){
			col = fill;
			thickness = weight;
		}


	}

	public class Circle{
		private float cx, cy, diameter;
		private int col, scol;
		private float thickness;
		private boolean filled = false;

		/**
		 * Create an arrow 20 units long and 12 units at its thick end with a white body
		 * and thin black border.
		 * @param papp
		 */
		public Circle(){
			col = color(255);
			scol = color(0);
			thickness = 1;
			diameter = 20;
		}

		public Circle(float x, float y, float diam, int col, int scol, float weight, boolean filled){			
			cx = x;
			cy = y;
			this.diameter = diam;
			this.col = col;
			this.scol = scol;
			thickness = weight;
			this.filled = filled;
		}

		public void setPos(float x, float y){
			cx = x;
			cy = y;
		}

		public void draw() {
			// Prepare to draw the entity
			pushStyle();
			pushMatrix();
			translate(cx, cy);

			// Draw the entity
			if(thickness > 0){
				strokeWeight(thickness);
				stroke(scol);
			}
			else
				noStroke();
			if(filled)
				fill(col);
			else
				noFill();
			ellipse(0,0,diameter, diameter);

			// Finished drawing
			popMatrix();
			popStyle();
		}

		public void appearance(int fill, int stroke, float weight){
			col = fill;
			this.scol = stroke;
			thickness = weight;
		}

		public PVector getCentre(){
			return new PVector(cx,cy);
		}
	}

	public class Arc{

		private float cx, cy, diameter;
		private float sa, ea;
		private int col, scol;
		private float thickness;
		private boolean filled = false;

		/**
		 * Create an arrow 20 units long and 12 units at its thick end with a white body
		 * and thin black border.
		 * @param papp
		 */
		public Arc(){
			col = color(255);
			scol = color(0);
			thickness = 1;
			diameter = 20;
		}

		public Arc(float x, float y, float diam, float startAng, float endAng, int col, int scol, float weight, boolean filled){			
			cx = x;
			cy = y;
			sa = startAng;
			ea = endAng;
			this.diameter = diam;
			this.col = col;
			this.scol = scol;
			thickness = weight;
			this.filled = filled;
		}

		public void draw() {
			// Prepare to draw the entity
			pushStyle();
			pushMatrix();
			translate(cx, cy);

			// Draw the entity
			if(thickness > 0){
				strokeWeight(thickness);
				stroke(scol);
			}
			else
				noStroke();
			if(filled)
				fill(col);
			else
				noFill();
			arc(0,0,diameter, diameter, sa, ea);

			// Finished drawing
			popMatrix();
			popStyle();
		}

		public void appearance(int fill, float weight){
			col = fill;
			thickness = weight;
		}

		public PVector getCentre(){
			return new PVector(cx,cy);
		}
	}


	public void seekPic(){
		fname = "seek.jpg";
		float angle = radians(285);
		float speed = 180;
		float ox = 80;
		float oy = 230;
		float tx = 240;
		float ty = 40;
		float tangle = atan2(ty-oy,tx-ox);

		Dart d = new Dart(ox, oy, 50, angle, YELLOW, BLACK, 1);
		Line cv = new Line(DIR, ox, oy, speed, angle, BLACK, 2.2f, SOLID, NONE, ARROW);
		Line tv = new Line(DIR, ox, oy, speed, tangle, BLUE, 2, SOLID, NONE, ARROW);
		Target t = new Target(tx,ty,24, BLUE, 2.5f);

		PVector ep1 = cv.getTip();
		PVector ep2 = tv.getTip();
		Line deltaV = new Line(ENDS, ep1.x, ep1.y, ep2.x, ep2.y, GREY0, 1.6f, DASHED, NONE, ARROW);

		Line sf = new Line(ENDS, ep1.x, ep1.y, ep2.x, ep2.y, RED, 2.0f, SOLID, NONE, ARROW);
		sf.moveStartTo(ox,oy);

		d.draw();
		cv.draw();
		tv.draw();
		sf.draw();
		t.draw();
		deltaV.draw();

		// now draw text
		fill(0);
		noStroke();

		p0 = cv.getMidPoint();
		txt = "Current Velocity";
		text(txt, p0.x - 4 - textWidth(txt), p0.y);
		p0 = tv.getMidPoint();
		txt = "Desired Velocity";
		text(txt, p0.x + 8, p0.y + 4);
		p0 = sf.getMidPoint();
		txt = "Steering Force";
		text(txt, p0.x , p0.y - 4);
	}

	public void wanderPic(){
		fname = "wander.jpg";
		float ox = 30;
		float oy = 100;
		float wd = 160;
		float wr = 50;

		Dart d = new Dart(ox, oy, 30, 0, YELLOW, BLACK, 1);
		Circle wcirc = new Circle(wd + ox, oy, 2*wr, 0, CYAN, 1, false);
		Circle wcentre = new Circle(wd + ox, oy, 6, CYAN, BLACK, 0, true);
		Line wdv = new Line(ENDS, ox, oy + wr + 6, ox + wd, oy + wr + 6, BLACK, 1.5f, DASHED, LINE, LINE);
		wdv.setText("Wander Distance", CENTER, BELOW, 0);
		float angle = radians(250);
		float tx = wd + ox + wr * cos(angle);
		float ty = oy + wr * sin(angle);
		Circle target = new Circle(tx,ty,12,CYAN, BLACK,1,true);
		Arc jitter = new Arc(wd + ox, oy, 2*wr - 8, radians(220), radians(280), BLUE0, BLUE, 3, true);
		Line wrv = new Line(DIR, ox + wd, oy, wr, radians(45), BLACK, 1.5f, DASHED, LINE, LINE);
		Line sf = new Line(ENDS, ox, oy, tx, ty, RED, 2, SOLID, NONE, ARROW);
		sf.setText("Steering Force", CENTER, ABOVE, 0);

		d.draw();
		jitter.draw();
		wcirc.draw();
		wcentre.draw();
		target.draw();
		sf.draw();
		wdv.draw();
		wrv.draw();

		fill(0);
		noStroke();
		p0 = wrv.getMidPoint();
		text("Wander Radius", p0.x, p0.y - 3);
		text("Target", tx - 26, ty - 10);

		p0 = sf.getMidPoint();
		angle = atan2(p0.y - oy, p0.x - ox);
		fill(BLUE);
		text("Jitter", tx - 6, ty + 26);
	}

	public void evadePic(){
		fname = "evade.jpg";
		float angle0 = radians(260);
		float speed0 = 80;
		float ox0 = 120, oy0 = 160;
		float angle1 = radians(190);
		float speed1 = 100;
		float ox1 = 270, oy1 = 60;

		Dart a0 = new Dart(ox0, oy0, 40, angle0, YELLOW, BLACK, 1);
		Dart a1 = new Dart(ox1, oy1, 40, angle1, GREEN0, BLACK, 1);
		Line cv0 = new Line(DIR, ox0, oy0, speed0, angle0, BLACK, 2, SOLID, NONE, ARROW);
		Line cv1 = new Line(DIR, ox1, oy1, speed1, angle1, BLACK, 2, SOLID, NONE, ARROW);
		p0 = cv1.getTip();
		Target t = new Target(p0.x,p0.y, 24, PINK, 2.5f);

		PVector ep2 = cv0.getTip();
		PVector ep1 = cv1.getTip();
		float angle = atan2(ep2.y - ep1.y, ep2.x - ep1.x);
		float mag = PVector.dist(ep1,ep2);

		Line gl0 = new Line(ENDS, ox0, oy0, p0.x, p0.y, GREY2, 1.5f, DASHED, NONE, NONE);
		Line gl1 = new Line(ENDS, ep2.x, ep2.y, p0.x, p0.y, GREY2, 1.5f, DASHED, NONE, NONE);
		Line deltaV = new Line(DIR, ep1.x, ep1.y, mag, angle, GREY0, 1.5f, DASHED, NONE, ARROW);
		deltaV.moveStartTo(ep2.x, ep2.y);
		Line sf = new Line(DIR, ep1.x, ep1.y, mag, angle, RED,  2, SOLID, NONE, ARROW);
		Line dv = new Line(ENDS, ep1.x, ep1.y, ox0, oy0, BLUE, 1.5f, SOLID, NONE, ARROW);
		dv.moveStartTo(ox0, oy0);
		sf.moveStartTo(ox0,oy0);

		gl0.draw();
		gl1.draw();
		a0.draw();
		a1.draw();
		t.draw();
		cv0.draw();
		cv1.draw();
		deltaV.draw();
		dv.draw();
		sf.draw();

		noStroke();
		txt = "Predicted Position";
		fill(GREEN0);
		p0 = cv1.getTip();
		text(txt, p0.x - textWidth(txt)/2, p0.y-15);
		fill(0);
		text("Evader", ox0, oy0 + 40);

		// Draw Legend
		translate(width - 80,height - 110);
		noFill();
		stroke(0);
		strokeWeight(1.6f);
		rect(0,8,70,92);
		Line v0 = new Line(ENDS, 4, 30, 66, 30, BLACK, 2, SOLID, NONE, ARROW);
		v0.setText("Velocity", CENTER, ABOVE, 0);
		Line v1 = new Line(ENDS, 4, 60, 66, 60, RED, 2, SOLID, NONE, ARROW);
		v1.setText("Steering", CENTER, ABOVE, 0);
		Line v2 = new Line(ENDS, 4, 90, 66, 90, BLUE, 1.7f, SOLID, NONE, ARROW);
		v2.setText("Desired", CENTER, ABOVE, 0);
		v0.draw();
		v1.draw();
		v2.draw();
		// End draw legend
	}


	public void pursuePic(){
		fname = "pursue.jpg";
		float angle0 = radians(260);
		float speed0 = 150;
		float ox0 = 120, oy0 = 230;
		float angle1 = radians(190);
		float speed1 = 80;
		float ox1 = 270, oy1 = 60;

		Dart a0 = new Dart(ox0, oy0, 40, angle0, YELLOW, BLACK, 1);
		Dart a1 = new Dart(ox1, oy1, 40, angle1, GREEN0, BLACK, 1);
		Line cv0 = new Line(DIR, ox0, oy0, speed0, angle0, BLACK, 2, SOLID, NONE, ARROW);
		Line cv1 = new Line(DIR, ox1, oy1, speed1, angle1, BLACK, 2, SOLID, NONE, ARROW);
		p0 = cv1.getTip();
		Target t = new Target(p0.x,p0.y, 24, PINK, 2.5f);

		PVector ep1 = cv0.getTip();
		PVector ep2 = cv1.getTip();
		float angle = atan2(ep2.y - ep1.y, ep2.x - ep1.x);
		float mag = PVector.dist(ep1,ep2);
		Line deltaV = new Line(DIR, ep1.x, ep1.y, mag, angle, GREY0, 1.5f, DASHED, NONE, ARROW);
		Line sf = new Line(DIR, ep1.x, ep1.y, mag, angle, RED, 2, SOLID, NONE, ARROW);
		sf.moveStartTo(ox0,oy0);
		Line dv = new Line(ENDS, ox0, oy0, ep2.x, ep2.y, BLUE, 1.5f, SOLID, NONE, ARROW);


		a0.draw();
		a1.draw();
		t.draw();
		cv0.draw();
		cv1.draw();
		deltaV.draw();
		dv.draw();
		sf.draw();

		noStroke();
		txt = "Predicted Position";
		fill(GREEN0);
		p0 = cv1.getTip();
		text(txt, p0.x - textWidth(txt)/2, p0.y-15);
		fill(0);
		text("Pursuer", ox0, oy0 + 40);

		// Draw Legend
		translate(10,height - 110);
		noFill();
		stroke(0);
		strokeWeight(1.6f);
		rect(0,8,70,92);
		Line v0 = new Line(ENDS, 4, 30, 66, 30, BLACK, 2, SOLID, NONE, ARROW);
		v0.setText("Velocity", CENTER, ABOVE, 0);
		Line v1 = new Line(ENDS, 4, 60, 66, 60, RED, 2, SOLID, NONE, ARROW);
		v1.setText("Steering", CENTER, ABOVE, 0);
		Line v2 = new Line(ENDS, 4, 90, 66, 90, BLUE, 1.7f, SOLID, NONE, ARROW);
		v2.setText("Desired", CENTER, ABOVE, 0);
		v0.draw();
		v1.draw();
		v2.draw();
		// End draw legend
	}

	public void ostacleAvoidPic_2(){
		fname = "ob_avoid_2.jpg";

		float dx = 100, dy = 50;
		float obx = dx + 120;

		Line gl0 = new Line(ENDS, 5,50,width-5,50, GREY2, 1.5f, DASHED, NONE, NONE);
		Dart a0 = new Dart(dx, dy, 40, 0, YELLOW, BLACK, 1);
		Circle ob0 = new Circle(obx, 95, 70, GREEN1, BLACK, 1.5f, true); 
		Line v = new Line(DIR, dx, dy, 100, 0, BLACK, 2, SOLID, NONE, ARROW);
		v.setText("Velocity", RIGHT, ABOVE, 14);
		Line b = new Line(DIR, dx, dy, 40, radians(180), RED, 1.8f, SOLID, LINE, ARROW);
		Line lat = new Line(DIR, obx, 50, 45, radians(270), RED, 1.8f, SOLID, LINE, ARROW);


		gl0.draw();
		a0.draw();
		ob0.draw();
		v.draw();
		b.draw();
		lat.draw();

		fill(BLACK);
		noStroke();
		text("Lateral", obx + 8, 20);
		text("Force", obx + 8, 36);
		p0 = b.getTip();
		txt = "Breaking";
		text(txt, p0.x - textWidth(txt)/1.6f, p0.y + 26);
		txt = "Force";
		text(txt, p0.x - textWidth(txt)/1.6f, p0.y + 42);
	}

	public void ostacleAvoidPic_1(){
		fname = "ob_avoid_1.jpg";

		Dart a0 = new Dart(72, 140, 30, radians(330), YELLOW, BLACK, 1);
		a0.setDetectBoxLength(140);
		Circle ob0 = new Circle(160, 120, 50, GREEN1, BLACK, 1.5f, true);
		Circle ob1 = new Circle(260, 45, 60, GREEN1, BLACK, 1.5f, true);
		Circle ob2 = new Circle(60, 75, 30, GREEN1, BLACK, 1.5f, true);

		ob0.draw();
		ob1.draw();
		ob2.draw();
		a0.draw();
	}

	public void wallAvoidPic_2(){
		fname = "wall_avoid_2.jpg";

		float dx = 60, dy = 40;
		float ftipX = dx + 110 * cos(radians(60));
		float ftipY = dy + 110 * sin(radians(60));
		float h = 100;

		Dart a0 = new Dart(dx, dy, 30, radians(60), YELLOW, BLACK, 1);
		a0.setWhiskerLength(110);	
		Line wall = new Line(ENDS, 0, h, width, h, GREY0, 4, SOLID, NONE, NONE);
		wall.setText("WALL", RIGHT, BELOW, 6);
		Line norm = new Line(DIR, width - 50, h, 40, radians(270), BLACK, 1.1f, SOLID, NONE, ARROW);
		Line pd = new Line(ENDS, ftipX, h, ftipX, ftipY, BLUE, 1.4f, SOLID, LINE, LINE);
		Line sf = new Line(ENDS, ftipX, h, ftipX, h-(ftipY-h), RED, 2.2f, SOLID, NONE, ARROW);

		wall.draw();
		a0.draw();
		norm.draw();
		pd.draw();
		sf.draw();

		fill(0);
		noStroke();
		p0 = pd.getMidPoint();
		text("Penetration", p0.x + 8, p0.y);
		text("Distance", p0.x + 8, p0.y + 12);
		p0 = norm.getTip();
		txt = "Normal";
		text(txt, p0.x - textWidth(txt)/2, p0.y - 4);
		txt = "OUTSIDE";
		text(txt, (width - textWidth(txt))/2, 16);
		p0 = sf.getTip();
		text("Steering Force", p0.x - 20, p0.y - 4);

	}

	public void wallAvoidPic_1(){
		fname = "wall_avoid_1.jpg";

		float sx0 = 20, ex0 = width - 50, h = height/2.6f; 
		Line vdir = new Line(ENDS, sx0, h, ex0 + 30, h, CYAN0, 7 , SOLID, BALL, ARROW);
		Line vnorm = new Line(DIR, ex0 - 20, h, 30, radians(90), BLACK, 1.2f, SOLID, NONE, ARROW );
		Line wall = new Line(ENDS, sx0, h, ex0, h, BLACK, 1.8f, SOLID, BALL, BALL );

		Line path1 = new Line(ENDS, sx0 + 34, 0, sx0 + 34, height - 20, GREEN0, 2f, SOLID, NONE, NONE);
		Line path2 = new Line(ENDS, sx0 + 60, height, sx0 + 60, h + 4, RED, 2f, SOLID, NONE, NONE);
		Dart d1 = new Dart(sx0+34, height-20, 20, radians(90), YELLOW, GREEN0,1);
		Dart d2 = new Dart(sx0+60, h + 10, 20, radians(270), YELLOW, RED,1);
		vdir.draw();
		wall.draw();
		vnorm.draw();
		path1.draw();
		path2.draw();
		d1.draw();
		d2.draw();

		fill(0);
		noStroke();
		txt = "P0";
		text(txt, sx0 - textWidth(txt)/2, h - 8);
		txt = "P1";
		text(txt, ex0 - textWidth(txt)/2, h - 8);
		p0 = wall.getMidPoint();
		text("INSIDE", p0.x + 6, h - 10);
		text("OUTSIDE", p0.x, h + 20);
		p0 = vnorm.getTip();
		txt = "Wall Normal";
		text(txt, p0.x - textWidth(txt)/2, p0.y + 16);
	}

	public void hidePic(){
		fname = "hide.jpg";

		float[] obX  = {50, 125, 220, 180};
		float[] obY  = {150, 50, 60, 140};
		float[] obRad  = {15, 30, 20, 30};
		float hx = 250, hy = 120;
		float px = 60, py = 80;

		Circle[] obs = new Circle[4];
		Circle[] hides = new Circle[4];
		Line[] lines = new Line[4];

		float[] sx = new float[4];
		float[] sy = new float[4];

		//	(float px, float py, float length, float ang, int fill, int stroke, float weight){

		Dart hunter = new Dart(hx,hy,28,radians(220), RED, BLACK, 1.2f);
		Dart prey = new Dart(px,py,28,radians(350), YELLOW, BLACK, 1.2f);

		//Circle(float x, float y, float diam, int col, int scol, float weight, boolean filled){			
		for(int i = 0; i < 4; i++){
			obs[i] = new Circle(obX[i], obY[i], 2*obRad[i], GREEN2, BLACK, 1.2f, true);
			obs[i].draw();
		}

		float[] dash = new float[] {2,4};
		for(int i = 0; i < 4; i++){
			float angle = atan2(obY[i] - hy, obX[i] - hx);
			float dist = sqrt( (obX[i] - hx) * (obX[i] - hx) + (obY[i] - hy) * (obY[i] - hy) );
			dist += obRad[i] + 20;
			sx[i] = hx + dist * cos(angle);
			sy[i] = hy + dist * sin(angle);
			lines[i] = new Line(ENDS, sx[i], sy[i], hx, hy, GREY1, 1.4f, DASHED, NONE, NONE);
			lines[i].setDash(dash);
			lines[i].draw();
		}

		hunter.draw();
		prey.draw();

		for(int i = 0; i < 4; i++){
			hides[i] =  new Circle(sx[i], sy[i], 8, PINK, RED, 1, true);
			hides[i].draw();
		}
		Line dv = new Line(ENDS, px, py, sx[1], sy[1], BLUE, 1.8f, SOLID, NONE, ARROW);
		dv.draw();
	}

	public void interposePic(){
		fname = "interpose.jpg";

		float ang0 = radians(280), ang1 = radians(240), angi = radians(290);
		float s0 = 70, s1 = 50, si = 80;
		float x0 = 20, y0 = height - 110;
		float x1 = 130, y1 = height - 130;
		float xi = 90, yi = height - 30;

		//float px, float py, float length, float ang, int fill, int stroke, float weight){
		Dart d0 = new Dart(x0, y0, 20, ang0, GREEN0, BLACK, 1.2f);
		Dart d1 = new Dart(x1, y1, 20, ang1, GREEN0, BLACK, 1.2f);
		Dart di = new Dart(xi, yi, 20, angi, YELLOW, BLACK, 1.2f);

		Line v0 = new Line(DIR, x0, y0, s0, ang0, BLACK, 1.2f, SOLID, NONE, ARROW);
		Line v1 = new Line(DIR, x1, y1, s1, ang1, BLACK, 1.2f, SOLID, NONE, ARROW);
		Line vi = new Line(DIR, xi, yi, si, angi, BLACK, 1.2f, SOLID, NONE, ARROW);
		// New position darts
		p0 = v0.getMidPoint();
		p1 = v1.getMidPoint();

		Dart d0a = new Dart(p0.x, p0.y, 20, ang0, GREEN_1, GREY1, 1.2f);
		Dart d0b = new Dart(p1.x, p1.y, 20, ang1, GREEN_1, GREY1, 1.2f);

		Line join = new Line(ENDS, p0.x, p0.y, p1.x, p1.y, GREY1, 1, DASHED, NONE, NONE);
		join.setDash(new float[]{2,4});

		p0 = join.getMidPoint();

		Line dv = new Line(ENDS, xi, yi, p0.x, p0.y, BLUE, 1.3f, SOLID, NONE, ARROW);
		p1 = vi.getTip();
		Line deltaV = new Line(ENDS, p1.x, p1.y, p0.x, p0.y, GREY0, 1.2f, DASHED, NONE, ARROW);
		Line sf = new Line(ENDS, p1.x, p1.y, p0.x, p0.y, RED, 1.5f, SOLID, NONE, ARROW);
		sf.moveStartTo(xi,yi);


		d0.draw();
		d1.draw();
		d0a.draw();
		d0b.draw();
		join.draw();
		di.draw();
		v0.draw();
		v1.draw();
		vi.draw();
		dv.draw();
		deltaV.draw();
		sf.draw();

		// Draw Legend
		translate(180, height - 150);
		noFill();
		stroke(0);
		strokeWeight(1.6f);
		rect(0,8,70,92);
		Line vl0 = new Line(ENDS, 4, 30, 66, 30, BLACK, 2, SOLID, NONE, ARROW);
		vl0.setText("Velocity", CENTER, ABOVE, 0);
		Line vl1 = new Line(ENDS, 4, 60, 66, 60, RED, 2, SOLID, NONE, ARROW);
		vl1.setText("Steering", CENTER, ABOVE, 0);
		Line vl2 = new Line(ENDS, 4, 90, 66, 90, BLUE, 1.7f, SOLID, NONE, ARROW);
		vl2.setText("Desired", CENTER, ABOVE, 0);
		vl0.draw();
		vl1.draw();
		vl2.draw();
		// End draw legend
	}

	public void pathPic(){
		fname = "path.jpg";
		float[] px  = {50, 20, 80, 100, 180, 150};
		float[] py  = {160,100, 80, 20, 50, 140};
		Circle[] nodes = new Circle[px.length];
		Line[] routes = new Line[px.length - 1];

		for(int i = 0; i < nodes.length; i++){
			nodes[i] = new Circle(px[i], py[i], 10, PINK, RED, 1.2f, true);
			nodes[i].draw();
		}

		for(int i = 0; i < nodes.length - 1; i++){
			routes[i] = new Line(ENDS, px[i], py[i], px[i+1], py[i+1], BLACK, 1.5f, SOLID, NONE, ARROW);
			routes[i].draw();
		}

		fill(0);
		noStroke();
		txt = "Start";
		text(txt, px[0] - textWidth(txt)/2, py[0] + 18);
		txt = "Finish";
		text(txt, px[nodes.length - 1] - textWidth(txt)/2, py[nodes.length - 1] + 18);

	}

	public void offsetPic(){
		fname = "offset.jpg";

		PImage arrow = loadImage("plane.png");
		PImage redarrows = loadImage("redarrows.jpg");

		float ox = width - 80, oy = height/2;
		float[] px  = {0, -50, -50, -100, -100, -150, -150, -150, -150};
		float[] py  = {0, -30,  30, -60,  60, -90, -35,  35,  90};

		Line haxis = new Line(ENDS, -190, 0, width - ox - 10, 0, GREY0, 1.5f, SOLID, NONE, ARROW);
		Line vaxis = new Line(ENDS, 0, -(oy - 10), 0, (oy - 10), GREY0, 1.5f, SOLID, NONE, ARROW);

		Bitmap[] planes = new Bitmap[9];
		Circle[] spots = new Circle[9];
		for(int i = 0; i < planes.length; i++){
			planes[i] = new Bitmap(arrow, px[i], py[i], 0);
			if(i == 0)
				spots[i] = new Circle(px[i], py[i], 10, PINK0, PINK0, 0, true);
			else
				spots[i] = new Circle(px[i], py[i], 10, YELLOW, YELLOW, 0, true);
		}

		imageMode(CENTER);
		float imgCx = 32 + redarrows.width/2;
		float imgBy = 20 + (height + redarrows.height)/2;
		image(redarrows, 32 + redarrows.width/2, oy);
		txt = "Royal Air Force Red Arrows";
		fill(0);
		noStroke();
		text(txt, imgCx - textWidth(txt)/2, imgBy);


		translate(ox,oy);
		haxis.draw();
		vaxis.draw();
		for(int i = 0; i < planes.length; i++){
			planes[i].draw();
			spots[i].draw();
		}

		fill(0);
		noStroke();
		p0 = haxis.getTip();
		p1 = vaxis.getTip();
		text("X", p0.x - 16, p0.y - 6);
		text("Y", p1.x + 6, p1.y - 10);
	}

	public void nonpenPic(){
		fname = "nonpen.jpg";

		float dx1 = width /4, dx2 = 3 * dx1;
		float midX = width /2;
		float dy = height/2;
		float cr = 50;
		float diffY = 20;
		int crCol = color(200,128,128,128);

		Dart d0 = new Dart(0, -diffY, 50, radians(40), YELLOW, BLACK, 1);
		Circle c0 = new Circle(0, -diffY, cr, crCol, crCol, 0, true);
		Dart d1 = new Dart(0, diffY, 50, radians(0), YELLOW, BLACK, 1);
		Circle c1 = new Circle(0, diffY, cr, crCol, crCol, 0, true);
		Line line = new Line(ENDS, 0, -diffY, 0, diffY, BLACK, 1.1f, SOLID, ARROW, ARROW);
		Line becomes = new Line(ENDS, midX-20, dy, midX+20, dy, BLACK, 3f, SOLID, NONE, ARROW);

		pushMatrix();
		translate(dx1, dy);
		rotate(radians(15));

		c0.draw();
		c1.draw();
		d0.draw();
		d1.draw();
		line.draw();
		popMatrix();

		diffY = 25;
		d0.setPos(0, -diffY);
		c0.setPos(0, -diffY);
		d1.setPos(0, diffY);
		c1.setPos(0, diffY);

		pushMatrix();
		translate(dx2, dy);
		rotate(radians(15));

		c0.draw();
		c1.draw();
		d0.draw();
		d1.draw();

		popMatrix();
		becomes.draw();
	}

	public void groupPic1(){
		fname = "group1.jpg";

		float[] vp = { 70, 230, 390 };
		float[] hp = { 70, 226 };

		float[] px  = {0,  40, -30, -45,  -5};
		float[] py  = {0,  -4,  25,  -2, -43};
		float[] ang = { radians(-10), radians(140), radians(60), radians(340), radians(300) };
		float[] angAlign = { ang[0], ang[0], ang[0], ang[0], ang[0] };

		Dart[] darts = new Dart[5];
		Line[] titles = new Line[3];
		Circle n = new Circle(0, 0, 100, GREY2, GREY2, 0, true);
		//	public Dart(float px, float py, float length, float ang, int fill, int stroke, float weight){

		for(int i = 0; i < darts.length; i++){
			if(i == 0)
				darts[i] = new Dart(0,0,18,0,YELLOW,BLACK,1);
			else
				darts[i] = new Dart(0,0,18,0,PINK,BLACK,1);	
		}
		titles[0] = new Line(ENDS, hp[0], vp[0] + 60, hp[1], vp[0] + 60, BLACK, 1.5f, SOLID, NONE, ARROW);
		titles[0].setText("Separation", CENTER, BELOW, 0);
		titles[1] = new Line(ENDS, hp[0], vp[1] + 60, hp[1], vp[1] + 60, BLACK, 1.5f, SOLID, NONE, ARROW);
		titles[1].setText("Alignment", CENTER, BELOW, 0);
		titles[2] = new Line(ENDS, hp[0], vp[2] + 60, hp[1], vp[2] + 60, BLACK, 1.5f, SOLID, NONE, ARROW);
		titles[2].setText("Cohesion", CENTER, BELOW, 0);

		groupSubPic1(hp[0], vp[0], n, darts, 1, px, py, ang);
		groupSubPic1(hp[1], vp[0], n, darts, 1.3f, px, py, ang);

		groupSubPic1(hp[0], vp[1], n, darts, 1, px, py, ang);
		groupSubPic1(hp[1], vp[1], n, darts, 1f, px, py, angAlign);

		groupSubPic1(hp[0], vp[2], n, darts, 1, px, py, ang);
		groupSubPic1(hp[1], vp[2], n, darts, 0.7f, px, py, ang);

		titles[0].draw();
		titles[1].draw();
		titles[2].draw();
	}

	public void groupSubPic1(float tx, float ty, Circle n, Dart[] d, float dist, float[] x, float[] y, float[] a){
		pushMatrix();
		translate(tx, ty);
		n.draw();
		for(int i = 0; i < d.length; i++){
			d[i].setPos(dist * x[i], dist * y[i], a[i]);
			d[i].draw();
		}
		popMatrix();
	}

	private void buildPic_1() {
		fname = "build01.jpg";
		World world = new World(200,200);

		//		Vector2D[] contour = new Vector2D[]{
		//				new Vector2D(65,140),
		//				new Vector2D(100,160),
		//				new Vector2D(160,125),
		//				new Vector2D(125,85),
		//				new Vector2D(115,40),
		//				new Vector2D(55,40),
		//				new Vector2D(70,90)
		//		};
		//		Building b = new Building(contour);

		Building[] bs = Building.makeFromXML(this, "ai4g/building.xml");
		Building b = bs[0];

		BuildingPic bpic = new BuildingPic(this, color(255,255,200), color(160,160,0), 2);
		b.renderer(bpic);
		world.add(b);

		Vector2D[] ea = b.expandedContour(8);

		world.draw();

		// draw vertex order
		for(int i = 1; i < ea.length; i++){
			Line line = new Line(ENDS, (float)ea[i-1].x, (float)ea[i-1].y, (float)ea[i].x, (float)ea[i].y, color(128), 1.5f, DASHED,  NONE, ARROW );
			line.draw();
		}
		// number vertex order
		ea = b.expandedContour(16);
		fill(0);
		noStroke();
		//		for(int i = 0; i<ea.length; i++){
		//			Vector2D p = Vector2D.sub(ea[i], contour[i]);
		//			p.normalize().mult(22).add(contour[i]);
		//			text(""+i, (float) p.x-4, (float)p.y+2);
		//		}
	}

	public final int DIR = 0;
	public final int ENDS = 1;

	public final int E0 = 101;
	public final int E1 = 102;

	public final int NONE = 201;
	public final int ARROW = 202;
	public final int LINE = 203;
	public final int BALL = 204;

	public final int SOLID = 301;
	public final int DASHED = 302;

	public final int ABOVE = 401;
	public final int BELOW = 402;


	int w, h;
	String fname;
	int YELLOW, YELLOW0, BLACK, GREY0, GREY1, GREY2, RED;
	int BLUE, CYAN, PINK, PINK0, GREEN0, GREEN1, GREEN2, CYAN0, PURPLE;
	int YELLOW_0, GREEN_1, BLUE0, WHITE;
	Graphics2D g2;
	PGraphicsJava2D pg;
	PVector p0, p1;
	String txt;

}


